/**
 * @copyright (C) COPYRIGHT 2022 Fortiortech Shenzhen
 * @file      main.c
 * @author    Fortiortech  Appliction Team
 * @since     Create:2022-12-29
 * @date      Last modify:2022-12-29
 * @note      Last modify author is Leo.li
 * @brief     Can Init/ Send /Receive/deal with
 */
#include <MyProject.h>

/*---------------------------- 变量定义 ------------------------------------*/
can_message_t xdata can_receive_msg; // 保存接收报文
can_message_t xdata can_send_msg;    // 保存发送报文
/*---------------------------- 宏 定 义 ------------------------------------*/

/**
 * @brief	设置 CAN 总线为休眠模式
 */
void set_can_to_sleep_mood(void)
{
    SetBit(CAN_CR1, SLPREQ);
}

/**
 * @brief	将 CAN 总线从休眠中唤醒
 */
void exti_sleep_mood(void)
{
    ClrBit(CAN_CR1, SLPREQ);
}

#define FIL_IDE (1) // 0-->标准帧  1-->扩展帧
#define FIL_RTR (0) // 0-->数据帧  1-->远程帧

/* tq = (BRP + 1)/24MHz
    tSEG1 = tq * (SEG1 + 1)
    tSEG2 = tq * (SEG2 + 1)
    baudrate = 1 / (tq + tSEG1 + tSEG2)
 */
#define RESYN (2)
#define BRP (11)
#define SEG1 (2) // 时间段 1
#define SEG2 (3) // 时间段 2
void can_init(void)
{

    // 配置 TJA1050 为高速模式
    SetBit(P0_OE, P07); // 配置 P07 为输出
    SetBit(P0_PU, P07); // 上拉输出
    ClrBit(P0, GP07);   // 输出低电平，
    
	// SetBit(CAN_CR0, RSTMOD);
    // ClrBit(CAN_CR0, RSTMOD);

    /* 时间段定义寄存器位定义
     *——————————————————————————————————————————————————————————————————————————
     *      |    7   |   6   |   5   |    4   |   3   |   2   |   1   |   0   |
     *——————————————————————————————————————————————————————————————————————————
     * BTR0 |<------------- RSV ------------->|<--- RESYN --->|<-- BRP[8-9]-->|
     * —————————————————————————————————————————————————————————————————————————
     * BTR1 |<-------------------------- BRP[0-7] --------------------------->|
     * —————————————————————————————————————————————————————————————————————————
     * BTR2 |  TTCM  |<-------- SEG2 -------->|<----------- SEG1------------->|
     * —————————————————————————————————————————————————————————————————————————
     */

    // 配置时间特性
    CAN_BTR0 = 0;
    CAN_BTR1 = 0;
    CAN_BTR2 = 0;

    CAN_BTR0 |= (RESYN << 2);       // CAN_BTRO = 00001000
    CAN_BTR1 = BRP;                 // CAN_BTR1 = 00001011
    CAN_BTR2 |= (SEG2 << 4) | SEG1; // CAN_BTR2 = 00110010

    // 过滤模式配置
    ClrBit(CAN_CR0, FILMOD); // 0 --> 双过滤    1--> 单过滤

    // 过滤配置
    CAN_FIR0 = ENGINE_SPEED_MSG_ID >> 21;
    CAN_FMR0 = 0xFF;
    CAN_FIR1 = ((ENGINE_SPEED_MSG_ID >> 18) & 0xE0) | (FIL_IDE << 3) | (FIL_RTR << 4) | ((ENGINE_SPEED_MSG_ID >> 15) & 0x07);
    CAN_FMR1 = 0xFF;

    CAN_FIR2 = MOTOR_CTRL_MSG_ID >> 21;
    CAN_FMR2 = 0xFF;
    CAN_FIR3 = ((MOTOR_CTRL_MSG_ID >> 18) & 0xE0) | (FIL_IDE << 3) | (FIL_RTR << 4) | ((MOTOR_CTRL_MSG_ID >> 15) & 0x07);
    CAN_FMR3 = 0xFF;

    // 配置协议版本 CAN 2.0
    ClrBit(CAN_CR0, CANREV);

    // 配置自动唤醒模式
    ClrBit(CAN_CR0, AWAKMOD); // 使能自动唤醒模式

    // 配置监听模式
    ClrBit(CAN_CR0, LISTEN);  // 禁止监听模式
    ClrBit(CAN_CR0, SELFTST); // 禁止自测模式
	
	// 中断配置
    SetBit(CAN_IER, ETYIE | BOFIE | PERIE | ERWIE | OVIE | ARBIE | TXIE | RXIE);
    
	SetBit(CAN_CR0, CAN_CH); // 端口转移：0:txd→P00,rxd→P01 1:txd→P05,rxd→P06
    SetBit(CAN_CR0, CANEN);  // 使能CAN总线
}

/**
 * @brief   读取CAN总线上对应函数
 * @note    若开启中断，需要注释掉SetBit(CAN_CR1, BUFRLS);
 */
void can_read(void)
{
    uint8 rdptr = CAN_CR2 & (RDPTR1 | RDPTR0);

    switch (rdptr)
    {
	// 缓冲区1
    case (0 | 0):
        can_receive_msg.ide = (CAN_RX0CR & 0x80);
        can_receive_msg.rtr = (CAN_RX0CR & 0x40);
        can_receive_msg.dlc = (CAN_RX0CR & 0x0F);

        if (can_receive_msg.ide)
        {
            can_receive_msg.ext_id = 0;
            can_receive_msg.ext_id |= (uint32)CAN_RX0ID0 << 21;
            can_receive_msg.ext_id |= (uint32)CAN_RX0ID1 << 13;
            can_receive_msg.ext_id |= (uint32)CAN_RX0ID2 << 5;
            can_receive_msg.ext_id |= (uint32)CAN_RX0ID3 >> 4;
        }
        else
        {
            can_receive_msg.std_id = 0;
            can_receive_msg.std_id |= CAN_RX0ID0 << 3;
            can_receive_msg.std_id |= CAN_RX0ID1 >> 5;
        }

        can_receive_msg.data0 = CAN_RX0DR0;
        can_receive_msg.data1 = CAN_RX0DR1;
        can_receive_msg.data2 = CAN_RX0DR2;
        can_receive_msg.data3 = CAN_RX0DR3;
        can_receive_msg.data4 = CAN_RX0DR4;
        can_receive_msg.data5 = CAN_RX0DR5;
        can_receive_msg.data6 = CAN_RX0DR6;
        can_receive_msg.data7 = CAN_RX0DR7;
        break;
	// 缓冲区2
    case (0 | RDPTR0):
        can_receive_msg.ide = (CAN_RX1CR & 0x80);
        can_receive_msg.rtr = (CAN_RX1CR & 0x40);
        can_receive_msg.dlc = (CAN_RX1CR & 0x0F);

        if (can_receive_msg.ide)
        {
            can_receive_msg.ext_id = 0;
            can_receive_msg.ext_id |= (uint32)CAN_RX1ID0 << 21;
            can_receive_msg.ext_id |= (uint32)CAN_RX1ID1 << 13;
            can_receive_msg.ext_id |= (uint32)CAN_RX1ID2 << 5;
            can_receive_msg.ext_id |= (uint32)CAN_RX1ID3 >> 4;
        }
        else
        {
            can_receive_msg.std_id = 0;
            can_receive_msg.std_id |= CAN_RX1ID0 << 3;
            can_receive_msg.std_id |= CAN_RX1ID1 >> 5;
        }

        can_receive_msg.data0 = CAN_RX1DR0;
        can_receive_msg.data1 = CAN_RX1DR1;
        can_receive_msg.data2 = CAN_RX1DR2;
        can_receive_msg.data3 = CAN_RX1DR3;
        can_receive_msg.data4 = CAN_RX1DR4;
        can_receive_msg.data5 = CAN_RX1DR5;
        can_receive_msg.data6 = CAN_RX1DR6;
        can_receive_msg.data7 = CAN_RX1DR7;
        break;
		
	// 缓冲区3
    case (RDPTR1 | 0):
        can_receive_msg.ide = (CAN_RX2CR & 0x80);
        can_receive_msg.rtr = (CAN_RX2CR & 0x40);
        can_receive_msg.dlc = (CAN_RX2CR & 0x0F);

        if (can_receive_msg.ide)
        {
            can_receive_msg.ext_id = 0;
            can_receive_msg.ext_id |= (uint32)CAN_RX2ID0 << 21;
            can_receive_msg.ext_id |= (uint32)CAN_RX2ID1 << 13;
            can_receive_msg.ext_id |= (uint32)CAN_RX2ID2 << 5;
            can_receive_msg.ext_id |= (uint32)CAN_RX2ID3 >> 4;
        }
        else
        {
            can_receive_msg.std_id = 0;
            can_receive_msg.std_id |= CAN_RX2ID0 << 3;
            can_receive_msg.std_id |= CAN_RX2ID1 >> 5;
        }

        can_receive_msg.data0 = CAN_RX2DR0;
        can_receive_msg.data1 = CAN_RX2DR1;
        can_receive_msg.data2 = CAN_RX2DR2;
        can_receive_msg.data3 = CAN_RX2DR3;
        can_receive_msg.data4 = CAN_RX2DR4;
        can_receive_msg.data5 = CAN_RX2DR5;
        can_receive_msg.data6 = CAN_RX2DR6;
        can_receive_msg.data7 = CAN_RX2DR7;
        break;

    default:
        break;
    }

    // SetBit(CAN_CR1, BUFRLS); // 如果开了中断请注释这句
}

#define CAN_FEEDBACK_ID (0x18FFD65D)

/**
 * @brief   通过 CAN 发送报文
 */
void can_send(void)
{
    can_send_msg.ext_id = CAN_FEEDBACK_ID;
    can_send_msg.ide = 1; // 0-->标准帧 1-->扩展帧
    can_send_msg.rtr = 0; // 0-->数据帧 1-->远程帧
    can_send_msg.dlc = 8;

    while (!ReadBit(CAN_SR, TXSUC))
        ;
    CAN_TXCR |= can_send_msg.ide << 7;
    CAN_TXCR |= can_send_msg.rtr << 6;
    CAN_TXCR |= can_send_msg.dlc;

    if (can_send_msg.ide)
    {
        CAN_TXID0 = can_send_msg.ext_id >> 21;
        CAN_TXID1 = (can_send_msg.ext_id >> 13) & 0xff;
        CAN_TXID2 = can_send_msg.ext_id >> 5;
        CAN_TXID3 = can_send_msg.ext_id << 3;
    }
    else
    {
        CAN_TXID0 = can_send_msg.std_id >> 3;
        CAN_TXID1 = can_send_msg.std_id << 5;
        CAN_TXID2 = 0;
        CAN_TXID3 = 0;
    }

    CAN_TXDR0 = can_send_msg.data0;
    CAN_TXDR1 = can_send_msg.data1;
    CAN_TXDR2 = can_send_msg.data2;
    CAN_TXDR3 = can_send_msg.data3;
    CAN_TXDR4 = can_send_msg.data4;
    CAN_TXDR5 = can_send_msg.data5;
    CAN_TXDR6 = can_send_msg.data6;
    CAN_TXDR7 = can_send_msg.data7;

    SetBit(CAN_CR1, TXREQ);
}
